package com.xinchuang.service.image.impl;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinchuang.common.KeyWordSystem;
import com.xinchuang.entity.common.FileTable;
import com.xinchuang.entity.image.ImageCut;
import com.xinchuang.entity.image.ImageSpecialSubject;
import com.xinchuang.entity.image.TaskRun;
import com.xinchuang.mapper.image.TaskRunMapper;
import com.xinchuang.service.RedisUseService;
import com.xinchuang.service.ReorganizeService;
import com.xinchuang.service.common.FileTableService;
import com.xinchuang.service.image.GDALService;
import com.xinchuang.service.image.ImageCutService;
import com.xinchuang.service.image.ImageSpecialSubjectService;
import com.xinchuang.service.image.TaskRunService;
import com.xinchuang.socket.WebSocketServer;
import com.xinchuang.util.RedisUtil;
import com.xinchuang.util.SnowflakeIdWorker;
import com.xinchuang.utils.MyUtil;
import com.xinchuang.utils.ObjectUtil;
import com.xinchuang.utils.OfficeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.Arrays;

/**
 * TODO
 *
 * @author zkwczx
 * @version 1.0
 * @date 2024/3/28 14:21
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TaskRunServiceImpl extends ServiceImpl<TaskRunMapper, TaskRun> implements TaskRunService {

    private final ImageCutService imageCutService;

    private final WebSocketServer webSocketServer;

    private final KeyWordSystem keyWordSystem;

    private final GDALService gdalService;

    private final RedisUtil redisUtil;

    private final ReorganizeService reorganizeService;

    private final FileTableService fileTableService;

    private final ImageSpecialSubjectService imageSpecialSubjectService;

    private final RedisUseService redisUseService;

    private SnowflakeIdWorker snow = new SnowflakeIdWorker(0, 0);

    @Override
    public void createAutoCorrectTask(String targetId, String baseId, String newId, String userId) {
        String uId = redisUseService.getUserId(userId);
        lambdaUpdate().eq(TaskRun::getUserId, uId).eq(TaskRun::getTaskId, targetId).eq(TaskRun::getTaskType, "AUTO").remove();
        startAuto(targetId, baseId, newId, userId);
    }

    @Async
    @Override
    public void startAuto(String targetId, String baseId, String newId, String userId) {
        String redisKey = targetId + "&&" + baseId + "&&" + newId + "&&" + userId;
        if (redisUtil.hasKey(redisKey)) {
            webSocketServer.sendToOneByUserId(userId, toJson("code", "AUTO_CORRECT_DOING", "message", "DOING"));
            return;
        } else {
            redisUtil.set(redisKey, "1", 60);
        }
        ImageCut b = imageCutService.lambdaQuery().eq(ImageCut::getId, baseId).one();
        ImageCut n = imageCutService.lambdaQuery().eq(ImageCut::getId, newId).one();
        String id = snow.nextId() + "";
        TaskRun run = new TaskRun();
        String url = "/auto/" + id + "/autoFile/";
        String projectUrl = url + "project/";
        if (ObjectUtil.isNotEmpty(b) && ObjectUtil.isNotEmpty(n)) {
            log.info("创建文件夹：" + keyWordSystem.getFILE_URL() + projectUrl);
            FileUtil.mkdir(keyWordSystem.getFILE_URL() + projectUrl);
            StringBuffer bSB = new StringBuffer();
            bSB.append("1" + "\n");
            bSB.append(keyWordSystem.getFILE_URL() + b.getImageUrl());
            FileUtil.writeString(bSB.toString(), keyWordSystem.getFILE_URL() + url + "TargetList.txt", "UTF-8");
            StringBuffer nSB = new StringBuffer();
            nSB.append("1" + "\n");
            nSB.append(keyWordSystem.getFILE_URL() + n.getImageUrl());
            FileUtil.writeString(nSB.toString(), keyWordSystem.getFILE_URL() + url + "RefList.txt", "UTF-8");
            if (FileUtil.isWindows()) {
                File file = FileUtil.newFile(keyWordSystem.getFILE_URL() + b.getImageUrl());
                String fileName = file.getName().substring(0, file.getName().lastIndexOf("."));
                boolean autoWin = MyUtil.autoWin(keyWordSystem.getExeUrl(), keyWordSystem.getFILE_URL() + url, keyWordSystem.getFILE_URL() + projectUrl, fileName);
                if (autoWin) {
                    String tifFile = "/auto/" + id + "/autoFile/project/" + fileName + "_REG.tif";
                    log.info("自动配准影像地址:" + tifFile);
                    ImageCut imageCut = gdalService.tif(targetId, tifFile, 10, "自动配准影像");
                    if (ObjectUtil.isNotEmpty(imageCut)) {
                        JSONObject json = new JSONObject();
                        json.put("id", imageCut.getId());
                        json.put("position", JSONArray.parseArray(imageCut.getPosition()));
                        json.put("positions", OfficeUtil.csvFile(keyWordSystem.getFILE_URL() + projectUrl + "/temp/" + fileName + "/mch_points.csv"));
                        webSocketServer.sendToOneByUserId(userId, toJson("code", "AUTO_CORRECT_END", "data", json.toJSONString()));
                        run.setId(id);
                        run.setUserId(redisUseService.getUserId(userId));
                        run.setTaskId(targetId);
                        run.setBaseId(baseId);
                        run.setNewId(newId);
                        run.setResultId(imageCut.getId());
                        run.setResultUrl(projectUrl + "/temp/" + fileName + "/");
                        run.setTaskType("AUTO");
                        run.setTaskStatus("DONE");
                        saveOrUpdate(run);
                        return;
                    }
                }
            } else {

            }
        }
        run.setId(id);
        run.setUserId(redisUseService.getUserId(userId));
        run.setTaskId(targetId);
        run.setBaseId(baseId);
        run.setNewId(newId);
        run.setTaskType("AUTO");
        run.setTaskStatus("ERROR");
        saveOrUpdate(run);
//        FileUtil.del(keyWordSystem.getFILE_URL() + "/auto/" + id);
        webSocketServer.sendToOneByUserId(userId, toJson("code", "AUTO_CORRECT_ERROR", "message", "自动纠正异常，请检查影像后重试"));
    }

    @Override
    public void createAutoRecognitionto(String imgId, JSONArray positions, String userId) {
        reorganizeService.autoRecognition(userId, imgId, positions);
    }

    @Async
    @Override
    public void createSubject(String userId, String subjectName, String format, String fileUrl) {
        ImageCut imageCut = gdalService.imageCut(redisUseService.getUserId(userId), fileUrl, 5, "专题影像");
        if (ObjectUtil.isEmpty(imageCut)) {
            webSocketServer.sendToOneByUserId(userId, toJson("code", "AUTO_SUBJECT_ERROR", "message", "该影像不支持此操作，请重新上传影像"));
            return;
        }
        imageSpecialSubjectService.remove(new LambdaQueryWrapper<ImageSpecialSubject>()
                .eq(ImageSpecialSubject::getRelId, redisUseService.getUserId(userId)));
        ImageSpecialSubject subject = new ImageSpecialSubject();
        subject.setRelId(redisUseService.getUserId(userId));
        subject.setSpecialName(subjectName);
        subject.setPlateType(format);
        imageSpecialSubjectService.save(subject);
        JSONObject json = new JSONObject();
        json.put("cutId", imageCut.getId());
        json.put("position", JSONArray.parseArray(imageCut.getPosition()));
        JSONObject resultJson = new JSONObject();
        resultJson.put("code", "AUTO_SUBJECT_END");
        resultJson.put("message", json);
        webSocketServer.sendToOneByUserId(userId, resultJson.toJSONString());
    }

    private String toJson(String code, String codeMsg, String message, String messageMsg) {
        JSONObject json = new JSONObject();
        json.put(code, codeMsg);
        json.put(message, messageMsg);
        return json.toJSONString();
    }

}
